package com.example.flutter_printer_plugin

import com.example.flutter_printer_plugin.inter.PrintInterface
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/** FlutterPrinterPlugin */
class FlutterPrinterPlugin: FlutterPlugin, MethodCallHandler {
  private lateinit var channel : MethodChannel
  private lateinit var mPrinter:PrintInterface
  companion object{
    const val RESULT_OK = "success"
  }

  override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    mPrinter = PrintInterface()
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_printer_plugin")
    channel.setMethodCallHandler(this)
  }

  override fun onMethodCall(call: MethodCall, result: Result) {
    when(call.method){
      "getPlatformVersion" ->{
        result.success("Android ${android.os.Build.VERSION.RELEASE}")
      }
      "isSupportPrinter" ->{
        val success = mPrinter.isSupportPrinter()
        result.success("$success")
      }
      "init" ->{
        val success = mPrinter.init()
        result.success("$success")
      }
      "free" ->{
        val success = mPrinter.free()
        result.success("$success")
      }
      "initPrint" ->{
        mPrinter.initPrint()
        result.success(RESULT_OK)
      }
      "sendData" ->{
        val parameter = call.argument<String>("content")
        if(parameter!=null){
          mPrinter.sendData(parameter)
          result.success(RESULT_OK)
        }else{
          sendError(result, arrayOf("content"))
        }
      }
      "printText" ->{
        val parameter = call.argument<String>("content")
        val charsetName = call.argument<String>("charsetName")
        if(parameter!=null && charsetName!=null){
          mPrinter.printText(parameter,charsetName)
          result.success(RESULT_OK)
        } else if(parameter!=null){
          mPrinter.printText(parameter)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("content"))
        }
      }
      "print" ->{
        val parameter = call.argument<String>("base64")
        val mode = call.argument<Int>("mode")
        val interval = call.argument<Int>("interval")
        val width = call.argument<Int>("width")
        val height = call.argument<Int>("height")
        if(parameter!=null && mode!=null && interval!=null){
          if(width!=null && height!=null){
            mPrinter.print(parameter,mode,interval,width,height)
          }else{
            mPrinter.print(parameter,mode,interval,380,480)
          }
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("base64","mode","interval"))
        }
      }
      "printImage" ->{
        val parameter = call.argument<String>("base64")
        val width = call.argument<Int>("width")
        val height = call.argument<Int>("height")
        if(parameter!=null){
          if(width!=null && height!=null){
            mPrinter.printImage(parameter,width,height)
          }else{
            mPrinter.printImage(parameter,380,480)
          }
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("base64"))
        }
      }
      "printBarcode" ->{
        val content = call.argument<String>("content")
        val barcodeType = call.argument<String>("barcodeType")
        if(content!=null && barcodeType!=null){
          mPrinter.printBarcode(content,barcodeType)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("content", "barcodeType"))
        }
      }
      "setFeedRow" ->{
        val type = call.argument<Int>("type")
        val n = call.argument<Int>("n")
        if(type!=null && n!=null){
          mPrinter.setFeedRow(type,n)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("type", "n"))
        }
      }
      "setGSPMode" ->{
        val x = call.argument<Int>("x")
        val y = call.argument<Int>("y")
        if(x!=null && y!=null){
          mPrinter.setGSPMode(x,y)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("x", "y"))
        }
      }
      "setPrintRowSpacing" ->{
        val spacing = call.argument<Int>("spacing")
        if(spacing!=null){
          mPrinter.setPrintRowSpacing(spacing)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("spacing"))
        }
      }
      "setPrintLeftMargin" ->{
        val nl = call.argument<Int>("nl")
        val nh = call.argument<Int>("nh")
        if(nl!=null && nh!=null){
          mPrinter.setPrintLeftMargin(nl,nh)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("nl","nh"))
        }
      }
      "setPrintAlignmentMode" ->{
        val n = call.argument<Int>("n")
        if(n!=null ){
          mPrinter.setPrintAlignmentMode(n)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("n"))
        }
      }
      "setPrintSpeed" ->{
        val speed = call.argument<Int>("speed")
        if(speed!=null ){
          mPrinter.setPrintSpeed(speed)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("speed"))
        }
      }
      "setPrintChromaLevel" ->{
        val chroma = call.argument<Int>("chroma")
        if(chroma!=null ){
          mPrinter.setPrintChromaLevel(chroma)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("chroma"))
        }
      }
      "restoreDefault" ->{
        mPrinter.restoreDefault()
        result.success(RESULT_OK)
      }
      "Black_label_On" ->{
        mPrinter.Black_label_On()
        result.success(RESULT_OK)
      }
      "Black_label_Off" ->{
        mPrinter.Black_label_Off()
        result.success(RESULT_OK)
      }
      "Feed_to_Next" ->{
        mPrinter.Feed_to_Next()
        result.success(RESULT_OK)
      }
      "setBarcodeHeight" ->{
        val height = call.argument<Int>("height")
        if(height!=null ){
          mPrinter.setBarcodeHeight(height)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("height"))
        }
      }
      "setBarcodeWidth" ->{
        val width = call.argument<Int>("width")
        if(width!=null ){
          mPrinter.setBarcodeWidth(width)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("width"))
        }
      }
      "setBarcodeHRI" ->{
        val n = call.argument<Int>("n")
        if(n!=null ){
          mPrinter.setBarcodeHRI(n)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("n"))
        }
      }
      "setUnderlineMode" ->{
        val n = call.argument<Int>("n")
        if(n!=null ){
          mPrinter.setUnderlineMode(n)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("n"))
        }
      }
      "setBoldMode" ->{
        val n = call.argument<Int>("n")
        if(n!=null ){
          mPrinter.setBoldMode(n)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("n"))
        }
      }
      "setFontDimension" ->{
        val n = call.argument<Int>("n")
        if(n!=null ){
          mPrinter.setFontDimension(n)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("n"))
        }
      }
      "Restore_factory" ->{
        val n = call.argument<Int>("n")
        if(n!=null ){
          mPrinter.Restore_factory(n)
          result.success(RESULT_OK)
        } else{
          sendError(result, arrayOf("n"))
        }
      }
      "getBaudRate" ->{
        result.success(mPrinter.getBaudRate())
      }
      "getVersion" ->{
        result.success(mPrinter.getVersion())
      }
      "getFontVersion" ->{
        result.success(mPrinter.getFontVersion())
      }
      else ->{
        result.notImplemented()
      }
    }
  }


  private fun sendError(result: Result, parameters: Array<String>) {
    val errorMessage = StringBuilder()
    errorMessage.append("Parameter")
    if (parameters.size > 1) {
      errorMessage.append("s")
    }
    errorMessage.append(" ")

    for ((index, parameter) in parameters.withIndex()) {
      errorMessage.append("'${parameter}'")
      if (index < parameters.size - 1) {
        errorMessage.append(" ")
      }
    }

    errorMessage.append(" is missing.")
    result.error("MISSING_PARAMETER", errorMessage.toString(), null)
  }


  override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
  }
}
